package amd64

import (
	"fmt"
	"strconv"
	"strings"
	"sync/atomic"

	"gitee.com/u-language/u-language/ucom/ast"
)

const (
	bit1 = " db "
	bit2 = " dw "
	bit4 = " dd "
	bit8 = " dq "
)

var (
	autoint int32 = 0
)

// int型数据
type IntData struct {
	Name  string
	Value string
}

func NewIntDate(Name string) *IntData {
	return &IntData{
		Name: Name,
	}
}

func (data *IntData) Kind() DataKindEnum {
	return Int
}

func (data *IntData) String() string {
	var buf strings.Builder
	if data == nil {
		buf.WriteString("&amd64.IntDate{ <nil> }")
	} else {
		buf.WriteString("&amd64.IntDate")
		buf.WriteString(fmt.Sprintf("%+v", *data))
	}
	return buf.String()
}

func (data *IntData) Asm() string {
	var buf strings.Builder
	buf.WriteString(data.Name)
	buf.WriteString(bit8)
	buf.WriteString(data.Value)
	buf.WriteString(" \n")
	return buf.String()
}

// float型数据
type FloatData struct {
	Name  string
	Value string
}

func NewFloatDate(Name string) *FloatData {
	return &FloatData{
		Name: Name,
	}
}

func (data *FloatData) Kind() DataKindEnum {
	return Float
}

func (data *FloatData) String() string {
	var buf strings.Builder
	if data == nil {
		buf.WriteString("&amd64.FloatDate{ <nil> }")
	} else {
		buf.WriteString("&amd64.FloatDate")
		buf.WriteString(fmt.Sprintf("%+v", *data))
	}
	return buf.String()
}

func (data *FloatData) Asm() string {
	var buf strings.Builder
	buf.WriteString(data.Name)
	buf.WriteString(bit4)
	buf.WriteString(data.Value)
	buf.WriteString(" \n")
	return buf.String()
}

// 解析变量为数据（Asm()可以获得对应汇编代码）
func ParserData(node *ast.VarNode) DataNode {
	var ret DataNode
	switch node.TYPE.Typ() {
	case "int":
		retdata := NewIntDate(node.Name)
		if node.Value.(*ast.Object).Name == "" {
			retdata.Value = "0"
		} else {
			retdata.Value = node.Value.(*ast.Object).Name
		}
		ret = retdata
	case "float":
		retdata := NewFloatDate(node.Name)
		if node.Value.(*ast.Object).Name == "" {
			retdata.Value = "0.0"
		} else {
			retdata.Value = node.Value.(*ast.Object).Name
		}
		ret = retdata
	}
	return ret
}

type AutoData struct {
	Name  string
	Value string
	size  string
}

func (data *AutoData) Kind() DataKindEnum {
	return Auto
}

func (data *AutoData) String() string {
	var buf strings.Builder
	if data == nil {
		buf.WriteString("&amd64.AutoData{ <nil> }")
	} else {
		buf.WriteString("&amd64.AutoData")
		buf.WriteString(fmt.Sprintf("%+v", *data))
	}
	return buf.String()
}

func (data *AutoData) Asm() string {
	var buf strings.Builder
	buf.WriteString(data.Name)
	buf.WriteString(data.size)
	buf.WriteString(data.Value)
	buf.WriteString(" \n")
	return buf.String()
}

// 创建临时变量
func NewAutoData(Value string, size int) *AutoData {
	var ret = new(AutoData)
	ret.Name = AutoName()
	ret.Value = Value
	switch size {
	case 1:
		ret.size = bit1
	case 2:
		ret.size = bit2
	case 4:
		ret.size = bit4
	case 8:
		ret.size = bit8
	}
	return ret
}

// 创建临时名称
func AutoName() string {
	var buf strings.Builder
	buf.Grow(13)
	buf.WriteString("auto_")
	n := atomic.AddInt32(&autoint, 1)
	buf.WriteString(strconv.Itoa(int(n)))
	return buf.String()
}
